package com.qp.bookkeeping.business.book.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.qp.bookkeeping.business.book.mapper.BookMapper;
import com.qp.bookkeeping.business.book.mapper.UserMapper;
import com.qp.bookkeeping.business.book.model.Bo.GroupMember;
import com.qp.bookkeeping.business.book.model.Do.ShareGroupDo;
import com.qp.bookkeeping.business.book.model.Do.UserDo;
import com.qp.bookkeeping.business.book.model.Dto.BookDto;
import com.qp.bookkeeping.business.book.model.Dto.ShareGroupDto;
import com.qp.bookkeeping.business.book.model.Dto.UserDto;
import com.qp.bookkeeping.business.book.model.req.*;
import com.qp.bookkeeping.business.book.model.rsp.UserInfoByPhoneRsp;
import com.qp.bookkeeping.business.book.model.rsp.UserInfoRsp;
import com.qp.bookkeeping.business.book.service.UserService;
import com.qp.bookkeeping.business.common.Exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xutianqi
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Resource
    UserMapper userMapper;

    @Resource
    BookMapper bookMapper;

    /**
     * @param userDo 数据库用户对象
     */
    @Override
    public void saveUser(UserDo userDo) {
        if (Objects.isNull(userDo)) {
            throw new BusinessException("请求参数为空！！");
        }
        String hwOpenId = userDo.getHwOpenId();
        if (Objects.isNull(hwOpenId)) {
            throw new BusinessException("hwOpenId为空！！");
        }
        UserDto userDto = UserDto.builder().hwOpenIds(Lists.newArrayList(hwOpenId)).build();
        List<UserDo> userDos = userMapper.selectUsers(userDto);
        if (CollectionUtil.isEmpty(userDos)) {
            userMapper.insertUser(userDo);
        } else {
            throw new BusinessException("当前用户已存在！");
        }
    }

    /**
     * 新建共享组
     *
     * @param createGroupReq 请求体
     */
    @Override
    public void createGroup(CreateGroupReq createGroupReq) {
        String initiatorPhone = createGroupReq.getInitiatorPhone();
        if (hasGroup(initiatorPhone)) {
            throw new BusinessException("已经存在共享组！！");
        }
        userMapper.insertGroup(ShareGroupDo.builder()
                .groupId(createGroupReq.getGroupId())
                .groupName(createGroupReq.getGroupName())
                .initiatorPhone(initiatorPhone)
                .memberPhone(initiatorPhone).build());
    }

    /**
     * 查询共享组
     *
     * @param queryGroupReq 查询共享组请求体
     */
    @Override
    public List<ShareGroupDo> queryGroup(QueryGroupReq queryGroupReq) {
        String member = queryGroupReq.getGroup().getMemberPhone();
        return userMapper.selectGroups(ShareGroupDto.builder().memberPhones(Lists.newArrayList(member)).build());
    }

    /**
     * 查询用户信息
     *
     * @param queryUserInfoReq 请求体
     * @return 返回体
     */
    @Override
    public UserInfoRsp queryUserInfo(QueryUserInfoReq queryUserInfoReq) {
        String hwOpenId = queryUserInfoReq.getHwOpenId();
        if (Objects.isNull(hwOpenId)) {
            throw new BusinessException("hwOpenId为空！！");
        }
        List<UserDo> userDos = userMapper.selectUsers(UserDto.builder().hwOpenIds(Lists.newArrayList(hwOpenId)).build());

        if (CollectionUtil.isEmpty(userDos)) {
            throw new BusinessException("用户不存在!!!");
        }
        UserDo userDo = userDos.get(0);
        UserInfoRsp userInfoRsp = UserInfoRsp.builder().user(userDo).build();
        fillShareGroups(userDo.getPhoneNumber(), userInfoRsp);
        return userInfoRsp;
    }

    /**
     * 通过手机号查询用户信息
     *
     * @param queryUserInfoReq 请求体
     * @return 返回体
     */
    @Override
    public UserInfoByPhoneRsp queryUserInfoByPhone(QueryUserInfoReq queryUserInfoReq) {
        String phoneNumber = queryUserInfoReq.getPhoneNumber();
        if (Objects.isNull(phoneNumber)) {
            throw new BusinessException("手机号为空！！");
        }
        List<UserDo> userDos = userMapper.selectUsers(UserDto.builder().phoneNumbers(Lists.newArrayList(phoneNumber)).build());

        if (CollectionUtil.isEmpty(userDos)) {
            throw new BusinessException("用户不存在!!!");
        }
        UserDo userDo = userDos.get(0);
        UserInfoByPhoneRsp userInfoByPhoneRsp = UserInfoByPhoneRsp.builder().user(userDo).build();

        // 处理共享组
        List<ShareGroupDo> shareGroupDos = userMapper.selectGroups(ShareGroupDto.builder().memberPhones(Lists.newArrayList(phoneNumber)).build());
        if (!CollectionUtils.isEmpty(shareGroupDos)) {
            ShareGroupDo shareGroupDo = shareGroupDos.get(0);
            // 填共享组
            userInfoByPhoneRsp.setShareGroup(shareGroupDo);

            userInfoByPhoneRsp.setGroupOwner(StringUtils.equals(phoneNumber, shareGroupDo.getInitiatorPhone()));

            List<GroupMember> allMembers = userMapper.selectGroupAndRole(ShareGroupDto.builder().groupIds(Lists.newArrayList(shareGroupDo.getGroupId())).build());
            userInfoByPhoneRsp.setGroupMembers(allMembers);
        }
        return userInfoByPhoneRsp;
    }

    /**
     * @param updateGroupReq 更新共享组请求体
     */
    @Override
    public void updateGroupName(UpdateGroupReq updateGroupReq) {
        userMapper.updateGroup(ShareGroupDto.builder().groupIds(updateGroupReq.getGroupIds()).groupName(updateGroupReq.getGroupName()).build());
    }

    /**
     * 加入共享组
     *
     * @param joinGroupReq 加入共享组请求体
     */
    @Override
    public void joinGroup(JoinGroupReq joinGroupReq) {
        String groupId = joinGroupReq.getGroupId();
        List<ShareGroupDo> shareGroupDos = userMapper.selectGroups(ShareGroupDto.builder().groupIds(Lists.newArrayList(groupId)).build());
        if (CollectionUtil.isEmpty(shareGroupDos)) {
            throw new BusinessException("未找到共享组！");
        }
        ShareGroupDo shareGroupDo = shareGroupDos.get(0);
        userMapper.insertGroup(ShareGroupDo.builder().groupId(groupId)
                .groupName(shareGroupDo.getGroupName())
                .initiatorPhone(shareGroupDo.getInitiatorPhone())
                .memberPhone(joinGroupReq.getMemberPhone()).build());
    }

    /**
     * 更新用户
     *
     * @param updateUserReq 更新用户请求体
     */
    @Override
    public void changePhone(UpdateUserReq updateUserReq) {
        String phoneNumber = updateUserReq.getPhoneNumber();
        String oriPhoneNumber = updateUserReq.getOriPhoneNumber();
        List<UserDo> userDos = userMapper.selectUsers(UserDto.builder().phoneNumbers(Lists.newArrayList(phoneNumber)).build());
        if (!CollectionUtils.isEmpty(userDos)) {
            throw new BusinessException("该手机号已绑定用户,若要绑定该手机号请联系客服！");
        }
        // 更新共享组成员
        userMapper.updateGroup(ShareGroupDto.builder()
                .memberPhone(phoneNumber)
                .oriMemberPhone(oriPhoneNumber).build());

        // 更新共享组创建人
        userMapper.updateGroup(ShareGroupDto.builder()
                .initiatorPhone(phoneNumber)
                .oriInitiatorPhone(oriPhoneNumber).build());

        // 更新收入账簿
        bookMapper.updateIncome(BookDto.builder().creatorPhone(phoneNumber).oriCreatorPhone(oriPhoneNumber).build());
        bookMapper.updateIncome(BookDto.builder().updaterPhone(phoneNumber).oriUpdaterPhone(oriPhoneNumber).build());
        // 更新支出账簿
        bookMapper.updateExpenditure(BookDto.builder().creatorPhone(phoneNumber).oriCreatorPhone(oriPhoneNumber).build());
        bookMapper.updateExpenditure(BookDto.builder().updaterPhone(phoneNumber).oriUpdaterPhone(oriPhoneNumber).build());
        //TODO: 更新column

        // 更新用户
        userMapper.updateUser(updateUserReq);
    }

    /**
     * 更新用户基础数据
     *
     * @param updateUserReq 更新用户请求体
     */
    @Override
    public void updateUser(UpdateUserReq updateUserReq) {
        userMapper.updateUser(updateUserReq);
    }

    /**
     * 删除共享组成员
     *
     * @param shareGroupDo 请求体
     */
    @Override
    public void deleteMember(ShareGroupDo shareGroupDo) {
        userMapper.deleteGroup(shareGroupDo);
    }

    private void fillShareGroups(String phoneNumber, UserInfoRsp userInfoRsp) {
        List<ShareGroupDo> initiatorGroups = userMapper.selectGroups(ShareGroupDto.builder().initiatorPhones(Lists.newArrayList(phoneNumber)).build());
        List<ShareGroupDo> memberGroups = userMapper.selectGroups(ShareGroupDto.builder().memberPhones(Lists.newArrayList(phoneNumber)).build());
        userInfoRsp.setInitiatorGroups(initiatorGroups);
        userInfoRsp.setMemberGroups(memberGroups);


        List<ShareGroupDo> allGroups = null;
        if (CollectionUtils.isEmpty(initiatorGroups) && CollectionUtils.isEmpty(memberGroups)) {
            log.info("手机号为" + phoneNumber + "的用户共享组为空");
        } else {
            List<String> allGroupIds = Lists.newArrayList();
            allGroupIds.addAll(Optional.ofNullable(initiatorGroups).orElse(new ArrayList<>()).stream().map(ShareGroupDo::getGroupId).distinct().collect(Collectors.toList()));
            allGroupIds.addAll(Optional.ofNullable(memberGroups).orElse(new ArrayList<>()).stream().map(ShareGroupDo::getGroupId).distinct().collect(Collectors.toList()));
            allGroups = userMapper.selectGroups(ShareGroupDto.builder().groupIds(allGroupIds).build());
        }

        userInfoRsp.setAllGroups(allGroups);

        // 设置用户昵称
        Set<String> phoneNumbers = new HashSet<>();
        if (!CollectionUtils.isEmpty(initiatorGroups)) {
            phoneNumbers.addAll(initiatorGroups.stream().map(ShareGroupDo::getInitiatorPhone).collect(Collectors.toList()));
            phoneNumbers.addAll(initiatorGroups.stream().map(ShareGroupDo::getMemberPhone).collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(memberGroups)) {
            phoneNumbers.addAll(memberGroups.stream().map(ShareGroupDo::getInitiatorPhone).collect(Collectors.toList()));
            phoneNumbers.addAll(memberGroups.stream().map(ShareGroupDo::getMemberPhone).collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(allGroups)) {
            phoneNumbers.addAll(allGroups.stream().map(ShareGroupDo::getInitiatorPhone).collect(Collectors.toList()));
            phoneNumbers.addAll(allGroups.stream().map(ShareGroupDo::getMemberPhone).collect(Collectors.toList()));
        }
        List<UserDo> userDos = userMapper.selectUsers(UserDto.builder().phoneNumbers(new ArrayList<>(Optional.of(phoneNumbers).orElse(Sets.newHashSet()))).build());
        Map<String, String> userMap = userDos.stream().collect(Collectors.toMap(UserDo::getPhoneNumber, UserDo::getNickName, (v1, v2) -> v1));

        if (!CollectionUtils.isEmpty(initiatorGroups)) {
            initiatorGroups.forEach((initiator) -> {
                initiator.setInitiatorName(userMap.get(initiator.getInitiatorPhone()));
                initiator.setMemberName(userMap.get(initiator.getMemberName()));
            });
        }

        if (!CollectionUtils.isEmpty(memberGroups)) {
            memberGroups.forEach((member) -> {
                member.setInitiatorName(userMap.get(member.getInitiatorPhone()));
                member.setMemberName(userMap.get(member.getMemberPhone()));
            });
        }

        if (!CollectionUtils.isEmpty(allGroups)) {
            allGroups.forEach((member) -> {
                member.setInitiatorName(userMap.get(member.getInitiatorPhone()));
                member.setMemberName(userMap.get(member.getMemberPhone()));
            });
        }
    }

    private boolean hasGroup(String initiatorPhone) {
        if (Objects.isNull(initiatorPhone)) {
            return false;
        }
        // 作为成员查询共享组
        List<ShareGroupDo> memberGroupDos = userMapper.selectGroups(ShareGroupDto.builder().memberPhones(Lists.newArrayList(initiatorPhone)).build());
        return !CollectionUtils.isEmpty(memberGroupDos);
    }
}
